{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 机器学习\n",
    "\n",
    "《机器学习算法原理与编程实践》\n",
    "\n",
    "\n",
    "理解数学公式与Numpy矩阵运算  \n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([[0., 0., 0., 0., 0.],\n",
       "        [0., 0., 0., 0., 0.],\n",
       "        [0., 0., 0., 0., 0.]]), array([[1., 1., 1., 1., 1.],\n",
       "        [1., 1., 1., 1., 1.],\n",
       "        [1., 1., 1., 1., 1.]]))"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#矩阵初始化\n",
    "import numpy as np# 导入Numpy包\n",
    "myZero=np.zeros([3,5])\n",
    "\n",
    "myOnes=np.ones([3,5])\n",
    "myZero,myOnes"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 第2章 中文文本分类    \n",
    "\n",
    "　　本章将以实例的形式，系统介绍中文文本分类的整体流程和相关算法。内容从文本挖掘的大背景开始，以文本分类算法为中心，详细介绍一个中文文本分类的项目，知识点涉及中文分词、向量空间模型、TF-IDF方法、几个典型的文本分类算法和评价指标等。   \n",
    "\n",
    "本章主要有：   \n",
    ">1. 朴素贝叶斯算法  \n",
    ">2. kNN最近邻算法\n",
    "\n",
    "代码讲解分为两部分：\n",
    ">1. 外部库如jieba分词、Scikit-Learning：提供详细的使用说明和案例代码。  \n",
    ">2. 算法：提供详细的讲解和注释  \n",
    "\n",
    "### 2.1 文本挖掘与文本分类的概念  \n",
    "\n",
    "文本挖掘（TextMining）是指从大量文本数据中抽取事先未知、可理解的、最终可用的知识的过程，同时运用这些知识更好地组织信息以便将来参考。\n",
    "\n",
    "\n",
    ">简而言之，文本挖掘就是从非结构化的文本中寻找知识的过程。  \n",
    "\n",
    "文本挖掘的7个领域：  \n",
    "\n",
    "可以说，在分析机器学习的数据源中最常见的知识发现主题是数据对象或事件转换为预定类别的过程。再根据类别进行专门的处理，这是分类系统的基本任务。文本分类也是如此，其实就是为用户给出每个文档找到所属的正确类别（主题或概念）。  \n",
    "\n",
    "目前，主要有两种文本分类的办法：  \n",
    "* 一 是基于模式系统（通过运用知识工程技术）  \n",
    "* 二 是分类模型（通过使用统计和/或机器学习技术）   \n",
    "\n",
    "专家系统的方法是将专家的知识以规则表达式的形式编码形成分类系统。机器学习的方法是一个广义的归纳过程，采用一组预分类的例子，通过训练建立分类。由于文件数量以指数速度的增加和知识专家的可用性变得越来越小，潮流趋势正转向机器学习——基于自动分类技术。  \n",
    "\n",
    "### 2.2 文本分类项目  \n",
    "\n",
    "给出中文语言的文本分类技术和流程，主要包括以下几个步骤：  \n",
    ">1. 预处理：去除文本噪声信息，例如HTML标签、文本格式转换、检测句子边界等。   \n",
    ">2. 中文分词：使用中文分词器为文本分词，并去除停用词。  \n",
    ">3. 构建词向量空间：统计文本词频，生成文本的词向量空间。   \n",
    ">4. 权重策略：TF-IDF方法：使用TF-IDF发现特征词，并抽取为反映文档主题的特征。  \n",
    ">5. 分类器：使用算法训练分类器。  \n",
    ">6. 评价分类结果：分类器的训练结果分析。  \n",
    "\n",
    "#### 2.2.1 文本预处理  \n",
    "\n",
    "**1.选择处理的文本范围**  \n",
    "\n",
    "对于一个实际的文本挖掘任务，文本范围是比较容易确定的。但是对于比较较长的文件，则需要决定是否使用整个文档或切分文档为各节、段落或句子。选择适当的范围取决于文本挖掘任务的目标：对于分类或聚类任务，往往把整个文档作为处理单位；对于情感分析、文档自动文摘或信息检索，段落或章节比较合适。  \n",
    "\n",
    "**2.建立分类文本语料库** \n",
    ">1) 训练集语料  \n",
    "　训练集语料是指已经分好的文本资源。目前比较好的中文分类语料库有复旦大学谭松波中文文本分类语料库（下载地址为）和搜狗新闻分类语料库(下载地址为)。    http://www.threadweb.cn/thread-1292-1-1.html   http://www.sogou.com/labs/dl/c.html\n",
    "\n",
    "\n",
    ">2) 测试集语料  \n",
    "　所谓测试集就是待分类的文本语料，可以是训练集的一部分，也可以是外部来源的文本语料。一般批量获取网络文本需要使用网络爬虫下载。  \n",
    "\n",
    ">3) 文本格式转换  \n",
    " 　一般都要转换为纯文本文件。为了提高性能，一般Python去除HTML标签，较多的使用lxml库，这是一个C语言编写的XML扩展库，比使用re正则表达式库的标签去除方式性能提高许多，适用于海量网络文本格式转换。  \n",
    "  \n",
    ">4) 检测句子边界：标记句子的结束  \n",
    "　句子边界检测室分解整个文档，并转换成单独句子的过程。\n",
    " \n",
    "#### 2.2.2 中文分词介绍  \n",
    "\n",
    "中文分词（Chinese Word Segmentation）指的是将一个汉字序列（句子）切分成一个单独的词。分词就是将连续的字序列按照一定的规范重新组合成词序列的过程。  \n",
    "\n",
    "在英文的行文中，单词是以空格作为自然分界符的。不过在词这一层上，中文要比英文复杂很多、困难很多。中文分词，不仅仅是中文文本分类的一大问题，，也是中文自然语言处理的核心问题之一。  \n",
    "\n",
    ">最终完全解决中文分词的算法是基于概率图模型的条件随机场（CRF）。这个算法是由Lafferty等人于2001年提出的。  \n",
    "\n",
    "\n",
    "分词是自然语言处理中最基本、最底层的模块，分词精度对后续应用模块影响很大，纵观整个自然语言处理领域，文本或句子的结构化表示是语言处理最核心的任务。   \n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Default Mode: 小明 1995 年 毕业 于 北京 清华大学\n",
      "小明 1995 年 毕业 于 北京 清华大学\n",
      "Full Mode 小/明/1995/年/毕业/于/北京/清华/清华大学/华大/大学\n",
      "小明/硕士/毕业/于/中国/科学/学院/科学院/中国科学院/计算/计算所/，/后/在/日本/京都/大学/日本京都大学/深造\n"
     ]
    }
   ],
   "source": [
    "#-*- coding utf-8 -*-\n",
    "import sys\n",
    "import os \n",
    "import jieba\n",
    "\n",
    "import imp\n",
    "# import regTrees  #网上找的资料更改不正确\n",
    "# imp.reload('regTrees')\n",
    "import imp\n",
    "\n",
    "#设置UTF-8 Unicode环境 \n",
    "# reload(sys)#应有这段代码\n",
    "# sys.setdefaultencoding('utf-8')#应有这段代码\n",
    "\n",
    "seg_list=jieba.cut(\"小明1995年毕业于北京清华大学\",cut_all=False)\n",
    "print(\"Default Mode:\",\" \".join(seg_list))  #默认划分\n",
    "\n",
    "seg_list=jieba.cut(\"小明1995年毕业于北京清华大学\")\n",
    "print(\" \".join(seg_list))\n",
    "\n",
    "seg_list=jieba.cut(\"小明1995年毕业于北京清华大学\",cut_all=True)\n",
    "print(\"Full Mode\",\"/\".join(seg_list)) #全划分\n",
    "#搜索引擎模式\n",
    "seg_list=jieba.cut_for_search(\"小明硕士毕业于中国科学院计算所，后在日本京都大学深造\")\n",
    "print(\"/\".join(seg_list))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "中文语料分词结束！\n"
     ]
    }
   ],
   "source": [
    "import jieba\n",
    "import os\n",
    "\n",
    "#定义两个函数，用于读取和保存文件\n",
    "def savefile(savepath,content): #保存至文件\n",
    "    fp=open(savepath,\"wb\")\n",
    "    fp.write(content.encode(encoding=\"utf-8\"))\n",
    "    fp.close()\n",
    "    \n",
    "def readfile(path): #读取文件\n",
    "    fp=open(path,\"rb\")\n",
    "    content=fp.read()\n",
    "    fp.close()\n",
    "    return content\n",
    "\n",
    "#以下是整个语料库的分词主程序\n",
    "corpus_path=\"D:/Coding/按书籍整理程序/机器学习算法原理与编程实践——郑捷（附完整代码及训练资源数据）/机器学习算法原理与编程实践（第2-9章节的源代码及数据集）/机器学习算法原理与编程实践（第2-9章节的源代码及数据集）/中文文本分类/train_corpus_before\"  #未分词分类语料库路径\n",
    "seg_path=\"D:/Coding/按书籍整理程序/机器学习算法原理与编程实践——郑捷（附完整代码及训练资源数据）/机器学习算法原理与编程实践（第2-9章节的源代码及数据集）/机器学习算法原理与编程实践（第2-9章节的源代码及数据集）/中文文本分类/train_corpus_after\"       #分词后分类语料库路径\n",
    "catelist=os.listdir(corpus_path)   #获取corpus_path下所有的子目录\n",
    "\n",
    "for mydir in catelist:\n",
    "    class_path=corpus_path+\"/\"+mydir+\"/\"\n",
    "    seg_dir=seg_path+\"/\"+mydir+\"/\"\n",
    "#     print(\"class_path=\",class_path,\"\\n\",\"seg_dir=\",seg_dir,)\n",
    "    if not os.path.exists(seg_dir): #是否存在目录，如果没有则创建\n",
    "        os.makedirs(seg_dir)\n",
    "    file_list=os.listdir(class_path)\n",
    "#     print(file_list)\n",
    "    for file_path in file_list:\n",
    "        fullname=class_path+file_path\n",
    "#         print(fullname)\n",
    "        content=readfile(fullname).strip()\n",
    "        content=content.replace(\"\\r\\n\".encode(encoding=\"utf-8\"),\"\".encode(encoding=\"utf-8\")).strip()\n",
    "        content_seg=jieba.cut(content)\n",
    "        #将处理后的文件保存到分词后语料目录\n",
    "        savefile(seg_dir+file_path,\" \".join(content_seg))\n",
    "print(\"中文语料分词结束！\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 2.2.5 权重策略：TF-IDF方法   \n",
    "\n",
    "前文有举例；  \n",
    "\n",
    "计算文本权重数量，最流行的方案是TF-IDF权重策略。\n",
    ">TF-IDF的含义：词频逆文档频率，其含义是：如果某个词语或短语在一篇文章中出现的频率高，并且在其他文章中很少出现，则认为此词或者短语具有很好的的类别区分能力。  \n",
    "\n",
    "词频（Term Frequency，TF）指的是某一个给定的词语在该文件中出现的频率。这个数字是对词数（Term Count）的归一化，以防止它偏向长的文件。对于在某一特定文件的词语来说，它的重要性可表示为：  \n",
    "\n",
    "$$\n",
    "TF_{ij}=\\frac{n_{i,j}}{\\sum_{k}n_{k,j}}\n",
    "$$\n",
    "\n",
    "上述公式中，分子是该词在文件中出现的次数，而分母则是文件中所有字词的出现次数之和。  \n",
    "\n",
    "逆向文件频率（Inverse Document Frequency，IDF）是一个词语普遍重要性的度量。某一特定词语的IDF，可以由总文件数目除以该词语的文件的数目，再将得到的商取对数得到。  \n",
    "\n",
    "$$\n",
    "IDF_{i}=log {\\frac{|D|}{\\big|\\{j:t_{i}\\in{d_j}\\}\\big|}}\n",
    "$$ \n",
    "\n",
    "其中，  \n",
    "* $|D|$：语料库中文件总数\n",
    "* $j$：包含词语的文件数目。如果该词语不在语料库中，就会导致分母为零，因此一般使用$1+\\big|\\{d\\in{D}:t\\in{d}\\}\\big|$作为分母。  \n",
    "\n",
    "\n",
    "然后计算TF和IDF的乘积。\n",
    "\n",
    "\n",
    "某一特定文件内的高词语频率，以及该词语在整个文件集合中的低文件频率（$TFIDF_{ij}=TF_{ij}I\\times{IDF_{ij}}$），可以产生出高权重的TF-IDF。因此，TF-IDF倾向于过滤掉常见的词语，保留重要词语。  \n",
    "\n",
    "代码实现：\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": false
   },
   "outputs": [],
   "source": [
    "#-*- coding:utf-8 -*-\n",
    "\n",
    "import sys\n",
    "import os\n",
    "from sklearn.datasets.base import Bunch  #引入bunch类\n",
    "import pickle as pickle #引入持久化类\n",
    "from sklearn import feature_extraction\n",
    "from sklearn.feature_extraction.text import TfidfTransformer#TF-IDF向量转换类\n",
    "from sklearn.feature_extraction.text import TfidfVectorizer#TF-IDF向量生成类\n",
    "\n",
    "#配置UTF-8输出环境\n",
    "#reload(sys)\n",
    "#sys.setdefaulttencoding('utf-8')\n",
    "\n",
    "#读取Bunch对象\n",
    "def readbunchobj(path):\n",
    "    file_obj=open(path,\"rb\")\n",
    "    bunch=pickle.load(file_obj)\n",
    "    file_obj.close()\n",
    "    return bunch\n",
    "#写入Bunch对象\n",
    "def writebunchobj(path,bunchobj):\n",
    "    file_obj=open(path,'wb')\n",
    "    pickle.dump(bunchobj,file_obj)\n",
    "    file_obj.close()\n",
    "    \n",
    "def readfile(path) :\n",
    "    fp = open(path, 'rb')\n",
    "    content = fp.read()\n",
    "    fp.close()\n",
    "    return content\n",
    "\n",
    "#读取停用词表\n",
    "stopword_path = \"D:/Coding/按书籍整理程序/机器学习算法原理与编程实践——郑捷（附完整代码及训练资源数据）/机器学习算法原理与编程实践（第2-9章节的源代码及数据集）/机器学习算法原理与编程实践（第2-9章节的源代码及数据集）/中文文本分类/train_word_bag/hlt_stop_words.txt\"\n",
    "stpwrdlst = readfile(stopword_path).splitlines()\n",
    "\n",
    "\n",
    "#导入分词后的词分量Bunch对象\n",
    "path=\"D:/Coding/按书籍整理程序/机器学习算法原理与编程实践——郑捷（附完整代码及训练资源数据）/机器学习算法原理与编程实践（第2-9章节的源代码及数据集）/机器学习算法原理与编程实践（第2-9章节的源代码及数据集）/中文文本分类/train_word_bag/train_set.dat\"#词向量空间保存路径\n",
    "bunch=readbunchobj(path)\n",
    "\n",
    "\n",
    "#构建TF-IDF词向量空间对象\n",
    "tfidspace = Bunch(target_name = bunch.target_name, label = bunch.label, filenames = bunch.filenames, tdm=[],vocabulary={})\n",
    "\n",
    "#使用TfidVectorizer初始化向量空间模型\n",
    "vectorizer = TfidfVectorizer(stop_words=stpwrdlst, sublinear_tf = True, max_df = 0.5)\n",
    "transformer = TfidfTransformer()\n",
    "#文本转为词频矩阵，单独保存字典文件\n",
    "tfidspace.tdm = vectorizer.fit_transform(bunch.contents)\n",
    "tfidspace.vocabulary = vectorizer.vocabulary_\n",
    "#创建词袋的持久化\n",
    "space_path=\"D:/Coding/按书籍整理程序/机器学习算法原理与编程实践——郑捷（附完整代码及训练资源数据）/机器学习算法原理与编程实践（第2-9章节的源代码及数据集）/机器学习算法原理与编程实践（第2-9章节的源代码及数据集）/中文文本分类/train_word_bag/tfdifspace.dat\"#词向量词袋保存路径\n",
    "writebunchobj(space_path, tfidspace)\n",
    "\n",
    "f=open(\"D:/Coding/按书籍整理程序/机器学习算法原理与编程实践——郑捷（附完整代码及训练资源数据）/机器学习算法原理与编程实践（第2-9章节的源代码及数据集）/机器学习算法原理与编程实践（第2-9章节的源代码及数据集）/中文文本分类/train_word_bag/tfdifspace.dat\",'rb')  \n",
    "bb=pickle.load(f)  \n",
    "f.close()  \n",
    "print(bb) #pickle文件不能直接阅读，必须通过这个函数\n",
    "print(\"结束\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 2.2.6 使用朴素贝叶斯分类模块\n",
    "\n",
    "最常用的文本分类方法及优缺点：\n",
    ">kNN最近邻算法原理最简单，分类精度尚可但速度最慢\n",
    "朴素贝叶斯算法对短文本分类效果最好，精度很高\n",
    "支持向量机算法优势是支持线性不可分的情况，精度上取中，\n",
    "\n",
    "\n",
    "\n",
    "|算法名称|精度|特点|\n",
    "|--:|:-:|--:|\n",
    "|kNN最近邻算法|分类精度尚可|原理最简单，但速度最慢|\n",
    "|朴素贝叶斯算法|精度很高|对短文本分类效果最好|\n",
    "|支持向量机算法|精度上取中|优势是支持线性不可分的情况|\n",
    "\n",
    "本文选择Scikit-Learn的朴素贝叶斯进行文本分类，测试集随机抽取自训练集中的文档集合，每个分类取10个文档，过滤掉1KB以下的文档。  \n",
    "\n",
    "训练步骤与训练集相同，首先是分词，之后生成文件词向量文件，直至生成词向量模型。不同的是，在训练词向量模型时，需要加载训练集词袋，将训练集产生的词向量映射到训练集词袋的词典中，生成向量空间模型。  \n",
    "\n",
    "\n",
    "代码先空白着\n",
    "\n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.3 分类算法：朴素贝叶斯  \n",
    "\n",
    "#### 2.3.1 贝叶斯公式推导  \n",
    "$\\dots\\dots\\dots\\dots\\dots$\n",
    "\n",
    "\n",
    "#### 2.3.1 朴素贝叶斯算法实现   \n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 92,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "([['my', 'dog', 'has', 'flea', 'problem', 'help', 'please'],\n",
       "  ['maybe', 'not', 'take', 'him', 'to', 'dog', 'park', 'stupid'],\n",
       "  ['my', 'dalmation', 'is', 'so', 'cute', 'I', 'love', 'him', 'my'],\n",
       "  ['stop', 'posting', 'stupid', 'worthless', 'garbage'],\n",
       "  ['mr', 'licks', 'ate', 'my', 'steak', 'how', 'to', 'stop', 'him'],\n",
       "  ['quit', 'buying', 'worthless', 'dog', 'food', 'stupid']],\n",
       " [0, 1, 0, 1, 0, 1])"
      ]
     },
     "execution_count": 92,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import sys\n",
    "import os\n",
    "from numpy import *\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import operator\n",
    "\n",
    "def loadDataSet():\n",
    "    \n",
    "    postingList =[['my','dog','has','flea','problem','help','please'],\n",
    "    ['maybe','not','take','him','to','dog','park','stupid'],\n",
    "    ['my','dalmation','is','so','cute','I','love','him','my'],\n",
    "    ['stop','posting','stupid','worthless','garbage'],\n",
    "    ['mr','licks','ate','my','steak','how','to','stop','him'],\n",
    "    ['quit','buying','worthless','dog','food','stupid']]\n",
    "    classVec = [0,1,0,1,0,1]#1是滥用，0是正常\n",
    "    return postingList,classVec\n",
    "    #postingList是训练文集，classVec是每个文本对应的分类\n",
    "\n",
    "postingList,classVec=loadDataSet()\n",
    "postingList,classVec\n",
    "\n",
    "#貌似不完整"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.4 分类算法：kNN  \n",
    "\n",
    ">一种基于向量相似度的分类算法\n",
    "\n",
    "#### 2.4.1 kNN算法原理  \n",
    "\n",
    "#### 2.4.2 kNN算法的Python实现  \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 94,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "array([[1., 0., 0., 0., 1., 1., 1., 0., 1., 0., 0., 0., 0., 0., 0., 1.,\n",
       "        0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
       "       [0., 0., 0., 0., 0., 1., 0., 0., 0., 1., 0., 1., 0., 0., 0., 0.,\n",
       "        0., 0., 0., 1., 1., 0., 0., 0., 0., 1., 0., 0., 1., 0., 0., 1.],\n",
       "       [0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 1., 0., 0., 1., 2.,\n",
       "        1., 0., 0., 0., 0., 0., 0., 1., 0., 0., 1., 0., 0., 1., 0., 0.],\n",
       "       [0., 0., 1., 1., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0.,\n",
       "        0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0.],\n",
       "       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 1., 0., 1., 0., 1.,\n",
       "        0., 1., 0., 0., 1., 1., 0., 0., 1., 0., 0., 0., 0., 0., 1., 0.],\n",
       "       [0., 1., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0.,\n",
       "        0., 0., 1., 1., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0.]])"
      ]
     },
     "execution_count": 94,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import sys\n",
    "import os\n",
    "from numpy import *\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import operator\n",
    "\n",
    "def loadDataSet():\n",
    "    classVec = [0,1,0,1,0,1]\n",
    "    postingList =[['my','dog','has','flea','problem','help','please'],\n",
    "    ['maybe','not','take','him','to','dog','park','stupid'],\n",
    "    ['my','dalmation','is','so','cute','I','love','him','my'],\n",
    "    ['stop','posting','stupid','worthless','garbage'],\n",
    "    ['mr','licks','ate','my','steak','how','to','stop','him'],\n",
    "    ['quit','buying','worthless','dog','food','stupid']]\n",
    "    return postingList,classVec\n",
    "\n",
    "#calc_wordfreq函数：生成普通的词频向量\n",
    "def calc_tf(trainset, classVec):\n",
    "    tempset              = set()\n",
    "    [tempset.add(word) for doc in trainset for word in doc]  #生成词典\n",
    "    vocabulary      = list(tempset)                                                        #转换成列表\n",
    "    vocablen = len(vocabulary)\n",
    "    doclength = len(trainset)\n",
    "    tf  = np.zeros([doclength,vocablen])                                           #训练集文件数*词典数 6x32的矩阵[[0,0,0,0,...,0]]\n",
    "    for indx in range(doclength) :                                                    #遍历所有的文本  doclength=6\n",
    "        for word in trainset[indx]:                                                        #遍历文本中的每个词\n",
    "            tf[indx,vocabulary.index(word)] += 1                                 #tf   训练值的权值矩阵\n",
    "    return tf\n",
    "\n",
    "#夹角cos计算公式\n",
    "def cosdist(vector1, vector2) :\n",
    "    return dot(vector1, vector2) / (linalg.norm(vector1) * linalg.norm(vector2))\n",
    "\n",
    "#KNN实现分类器\n",
    "#测试集testdata; 训练集:trainSet; 类别标签：listClasses; k:k个邻居数\n",
    "def classify(testdata, trainSet, labels, k) :\n",
    "    dataSetSize = trainSet.shape[0]                                                      #返回样本集的行数  6\n",
    "    distances = array(zeros(dataSetSize))                                           #[ 0.  0.  0.  0.  0.  0.]\n",
    "    for indx in range(dataSetSize) :                                                    #dataSetSize=6\n",
    "        distances[indx] = cosdist(testdata, trainSet[indx])\n",
    "    sortedDistIndicies = argsort(-distances)\n",
    "    classCount = {}\n",
    "    for i in range(k) :                                                                                  #获取角度最小的前K项作为参考项\n",
    "        voteIlabel = labels[sortedDistIndicies[i]]                                   #按排列顺序返回样本集对应的类别标签\n",
    "        classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1  #为字典classCount赋值，相同的key，其value加1\n",
    "    sortedClassCount = sorted(classCount.items(), key = operator.itemgetter(1),reverse = True)\n",
    "    return sortedClassCount[0][0]\n",
    "\n",
    "#算法测试\n",
    "k = 3\n",
    "dataSet, labels = loadDataSet()\n",
    "tf = calc_tf(dataSet, labels)\n",
    "print(classify(tf[2], tf, labels, k))\n",
    "tf\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
